<?php declare(strict_types=1);
/**
 * @author      xianganyall <xianganyall@gmail.com>
 * @copyright   2023-2025 owner
 **/

namespace Srv\Scripts\Tools;

use ArrayIterator;
use Phar;
use FilesystemIterator;

$srvPath            = dirname(__DIR__, 2).'/';
$rootPath           = dirname(__DIR__, 3).'/';
// 跳过的目录前缀[不支持正则,区分大小写]
$skipPathList       = [
    $srvPath.'Composer/vendor/composer/installed.json',
    $srvPath.'Composer/vendor/smarty/smarty/docs/',
    $srvPath.'Composer/vendor/smarty/smarty/demo/',
    $srvPath.'Composer/vendor/smarty/smarty/lexer/',
    $srvPath.'Composer/vendor/smarty/smarty/run-tests.sh',
    $srvPath.'Composer/vendor/smarty/smarty/run-tests-for-all-php-versions.sh',
    $srvPath.'Scripts/Tools/',
    $srvPath.'Scripts/start.local.php',
    $srvPath.'Conf/Conf.local.php',
    $srvPath.'Conf/ProtoSrc/',
];
$skipFileNameList   = [
    'CHANGELOG',
    'CHANGELOG.md',
    'CONTRIBUTING',
    'CONTRIBUTING.md',
    'LICENSE',
    'LICENSE.md',
    'README',
    'README.md',
    'SECURITY',
    'SECURITY.md',
    'composer.json',
    'composer.lock',
    '.gitignore',
];
$pharMetaData       = ['version' => '1.1.0.'.date('ymd'), 'author' => 'Srv', 'description' => 'buildTime:'.date('Y-m-d H:i:s')];
$pharFileName       = 'Srv.phar';
$pharFilePath       = $rootPath.$pharFileName;
if(file_exists($pharFilePath)) die('phar Exists, Please Delete: '.$pharFilePath."\n");
if(!file_exists($srvPath)) die('build Path Not Found: '.$srvPath."\n");
$stubContent        = <<<EOF_STUB
#!/usr/bin/env php
<?php
function getAllFileList(string \$dirPath, array &\$allFileList):bool
{
    if(is_dir(\$dirPath) && (\$dirHand = @opendir(\$dirPath))){
        while(\$fileName = @readdir(\$dirHand)){
            if(\$fileName != '.' && \$fileName != '..'){
                \$fullPath = rtrim(\$dirPath, '/').'/'.\$fileName;
                if(!is_dir(\$fullPath)){
                    \$allFileList[] = \$fullPath;
                }else{
                    if(!getAllFileList(\$fullPath, \$allFileList)) return false;
                }
            }
        }
        @closedir(\$dirHand);
        return true;
    }
    return false;
}
Phar::mapPhar('{$pharFileName}');
\$startPath = \$GLOBALS['argv'][1]??'';
if(strlen(\$startPath) < 1) \$startPath = 'help';
\$allFileList = [];
if(\$startPath === 'help'){
    \$pathDir = 'phar://{$pharFileName}/Scripts/';
    \$pathDirLength = strlen(\$pathDir);
    getAllFileList(\$pathDir, \$allFileList);
    if(count(\$allFileList) > 0) foreach(\$allFileList as \$filePath){
        echo (\$GLOBALS['argv'][0]??'').' '.substr(\$filePath, \$pathDirLength, -4)."\n";
    }
}else{
    require 'phar://{$pharFileName}/Scripts/'.\$startPath.'.php';
}
__HALT_COMPILER();
EOF_STUB;
$skipPathData           = [];
foreach ($skipPathList as $skipPath){
    $skipPath           = trim($skipPath);
    $skipPathLength     = strlen($skipPath);
    if($skipPathLength < 1) continue;
    $skipPathData[]     = ['length' => $skipPathLength, 'path' => $skipPath];
}
array_multisort(array_column($skipPathData, 'length'), SORT_NUMERIC, SORT_ASC, array_column($skipPathData, 'path'), SORT_STRING, SORT_ASC, $skipPathData);
$srvPathLength      = strlen($srvPath);
$Phar               = new Phar($pharFilePath, FilesystemIterator::CURRENT_AS_FILEINFO|FilesystemIterator::KEY_AS_FILENAME, $pharFileName);
$Phar->startBuffering();
function addAllFilePath(string $dirPath, int $srvPathLength, array $skipPathData, array $skipFileData, array &$fileList):bool
{
    if(is_dir($dirPath) && ($dirHand = @opendir($dirPath))){
        while($fileName = @readdir($dirHand)){
            if($fileName === '.' || $fileName === '..' || substr($fileName, 0, 1) === '.') continue;
            $fullPath           = rtrim($dirPath, '/').'/'.$fileName;
            if(is_dir($fullPath)){
                if(!addAllFilePath($fullPath, $srvPathLength, $skipPathData, $skipFileData, $fileList)) return false;
                continue;
            }
            $fullPathLength     = strlen($fullPath);
            $isSkip             = false;
            if(count($skipFileData) > 0 && in_array($fileName, $skipFileData, true)) $isSkip = true;
            if(!$isSkip && count($skipPathData) > 0) foreach ($skipPathData as $skipPathItem){
                if(!isset($skipPathItem['path']) || !isset($skipPathItem['length']) || $skipPathItem['length'] < 1 || $fullPathLength < $skipPathItem['length']) continue;
                if(substr($fullPath, 0, $skipPathItem['length']) === $skipPathItem['path']){
                    $isSkip     = true;
                    break;
                }
            }
            if(!$isSkip) $fileList[substr($fullPath, $srvPathLength)] = $fullPath;
        }
        @closedir($dirHand);
        return true;
    }
    return false;
}
$fileList       = [];
if(!addAllFilePath($srvPath, $srvPathLength, $skipPathData, $skipFileNameList, $fileList)){
    echo 'Fail: '.$pharFilePath."\n";
}else{
    $Phar->buildFromIterator(new ArrayIterator($fileList));
    $Phar->setStub($stubContent);
    $Phar->setMetadata($pharMetaData);
    $Phar->stopBuffering();
    echo 'Files: '.count($Phar)."\n";
    @chmod($pharFilePath, 0755);
    echo 'Success: '.$pharFilePath."\n";
}